<template>
	<div>reactivitetest</div>
	<div>reactive+ref原理</div>
	<h5>测试shallowRef：x.y:{{x.y}},x:{{x}}</h5>
	<button @click="x={y:888}">点我替换x={y:888}</button>
	<button @click="x.y++">点我x.y++,没有变化</button>
	<button @click="x=2">点我替换x=2</button>
	<button @click="x++">点我x++</button>
	<h5>测试shallowReactive：state.foo:{{state.foo}},state.nested.bar:{{state.nested.bar}}</h5>
	<button @click="state.foo++">点我state.foo++,变化</button>
	<button @click="state.nested.bar++">点我state.nested.bar++,不变化</button>
</template>

<script>
	import {
		ref,
		reactive,
		toRef,
		toRefs,
		shallowRef,
		isReactive,
		shallowReactive,
	} from 'vue'
	export default {
		setup() {
			console.clear()
			console.log('='.repeat(12), 'toRef')
			// toRef创建一个ref对象，其value指向对象中的某个属性，toRefs批量创建多个ref
			var person = reactive({
				name: 'agen',
				age: 18,
				job: {
					salary: 20
				}
			})
			var name1 = person.name
			// 此时修改name1，name1指向字符串，person.name值不改变
			name1 = 'agen1'
			console.log('name1', name1, person.name) //name1 agen1 agen
			// 此时的name2具有响应式，改变name2值，person.name值会改变
			var name2 = toRef(person, 'name')
			name2.value = 'agen2'
			console.log('name2', name2.value, person.name, person, name2) //name2 agen2 agen2
			var aaa = {
				a: 1
			}
			//批量修改对象属性值为响应式
			var person2 = toRefs(person)
			console.log('person2', person2, person2.job.value)

			//创建一个跟踪自身 .value变化的ref，但不会使其值也变成响应式的
			console.log('='.repeat(12), 'shallowRef')
			var foo = shallowRef({
				age: 0
			})
			foo.value.age = 1 //foo.value.age不具有响应式
			console.log('isReactive', foo.value.age, isReactive(foo.value), foo)
			var foo1 = ref({
				age: 0
			})
			foo1.value.age = 1
			console.log('isReactive', isReactive(foo1.value), foo1)

			//通过按钮测试值的改变情况
			var x = shallowRef({
				y: 0
			})
			x.y++
			console.log('shallowRef', x.value, x)
			x.value.y++
			console.log('shallowRef', x.value, x)

			console.log('='.repeat(12), 'shallowReactive')
			//创建一个响应式代理，跟踪自身property变化，property值不具有响应式
			// 只
			var state = shallowReactive({
				foo: 1,
				nested: {
					bar: 2
				}
			})
			state.foo++
			console.log('state.foo', state.foo, isReactive(state.foo), isReactive(state.nested), state)
			return {
				person,
				name1: name1,
				name2: name2,
				age1: toRef(person, 'age'),
				salary1: toRef(person.job, 'salary'),
				aaa,
				...{
					b: 2
				}, //等价于 b：2
				person2,
				...toRefs(person), //批量对象属性值为响应式，并展开对象的属性值
				x,
				state,
			}
		},
		data() {
			return {
				title: 'ref的原理+reactive'
			}
		},
		mounted() {
			// this.proxyTest();
			// this.reflectTest();
			this.reactiveTest();

		},
		methods: {
			//一个简单的Proxy,写了set, get两个方法
			proxyTest() {
				const user = {
					name: 'wangly19',
					age: 22,
					description: '一名掉头发微乎其微的前端小哥。'
				}
				const userProxy = new Proxy(user, {
					get(target, key) {
						console.log(`userProxy: 当前获取key为${key}`)
						if (target.hasOwnProperty(key)) return target[key]
					},
					set(target, key, value) {
						console.log(`userProxy: 当前设置值key为${key}， value为${value}`)
						let isWriteSuccess = false
						if (target.hasOwnProperty(key)) {
							target[key] = value
							isWriteSuccess = true
						}
						return isWriteSuccess
					}
				})

				console.log('myName=', userProxy.name)
				userProxy.age = 23
			},

			//Reflect是一个内置的对象,它的功能比较和Proxy的handles有点类似，在这一点基础上又添加了很多Object的方法
			reflectTest() {
				console.log('=============reflectTest')
				const user = {
					name: 'wangly19',
					age: 22,
					description: '一名掉头发微乎其微的前端小哥。'
				}
				console.log('change age before', Reflect.get(user, 'age'))
				const hasChange = Reflect.set(user, 'age', 23)
				console.log('set user age is done? ', hasChange ? 'yes' : 'no')
				console.log('change age after', Reflect.get(user, 'age'))
				const hasDelete = Reflect.deleteProperty(user, 'age')
				console.log('delete user age is done?', hasDelete ? 'yes' : 'none')
				console.log('delete age after', Reflect.get(user, 'age'))
			},

			//proxy reactive的原理是handle,而ref的原理是getter/setter
			reactiveTest() {
				console.log('=============reactiveTest')
				var count = ref(1)
				var obj = reactive({
					count
				})
				// ref 会被解包
				console.log(obj.count === count.value) //true
				count.value++
				obj.count++
				console.log(obj.count) // 3
				console.log(count.value) // 3

				//当将 ref 分配给 reactive property 时，ref 将被自动解包。
				var count = ref(1)
				var obj = reactive({})
				obj.count = count
				console.log(obj.count === count.value) //true
			},




		},
	}
</script>

<style>
</style>
